// NextUseRegAllocator.h
// A registers allocator based on Next-use

#ifndef NEXTUSEREGALLOCATOR_H
#define NEXTUSEREGALLOCATOR_H

#include "crossbit/common.h"
#include "crossbit/RegAllocator.h"
#include <vector>
#include <queue>
#include <map>
#include <deque>
#include <set>

namespace crossbit {


    class NextUseRegAllocator : public RegAllocator {

        public:
            NextUseRegAllocator(XTUint8 num_regs, CBOfSpillIn cb_spill_in, CBOfSpillOut cb_spill_out, CBOfRegToReg cb_regtoreg , XTUint32 * regs ) : source_regs(regs),RegAllocator(num_regs, cb_spill_in, cb_spill_out, cb_regtoreg)
            {	
            }

            virtual ~NextUseRegAllocator()
            {}

            // Allocate target register for virtual register
            virtual XTRegNum regAlloc(XTRegNum vreg, RegAccessMode mode);	        
            // Force allocate target register "expect" to "vreg"
            virtual XTRegNum regAllocForce(XTRegNum vreg, XTRegNum expect, RegAccessMode mode);
            // 
            virtual XTRegNum regAllocExpect(XTRegNum vreg, XTUint8 reg_mask, RegAccessMode mode);
            // Force "vreg" NOT to be allocated to "except"
            virtual XTRegNum regAllocForceExcept(XTRegNum vreg, XTRegNum except, RegAccessMode mode);

            virtual void regAllocReserve(XTRegNum reg);
            virtual void regAllocRelease(XTRegNum reg);

            // this is a auxilary function used for debugging
            void printNextUseInfo();
            void unmapIfNoNextUse(XTRegNum vreg);

            virtual void init(VBlock *vb);
            virtual void phaseTask();
            // increase the vinst_seq, and refresh the states of <code>ra_reg_table</code>
            void incrementVinstSeq()
            {
                ++vinst_seq;
                for( XTRegNum i = 0 ; i < 8 ; i ++ ){
                    if( ra_reg_table[i].status == ALLOCATED ){
                        XTRegNum vreg = ra_reg_table[i].mapped_to;
                        ra_vreg_spilled[vreg] = true;
                    }
                }
            }

        private:
            // collect the virtual register usage information from a <code>VBlock</code>
            void collectNextUseInfo(VBlock *vb);

            virtual XTRegNum regSpillOut(XTRegNum physical_reg);
            virtual void regSpillIn(XTRegNum vreg, XTRegNum treg);

            //Modified by suntingtao
            //vreg_used_list[50] is used to store the sequence of vregs used or defined in Vinst list.
            //the pair<XTInt32,RegAccessMode> stand for the sequece number and use mod(USE or DEF).
            const static XTInt32 MAX_VREG_NUM = 50;
            std::queue<std::pair<XTInt32,RegAccessMode> > ra_vreg_used_list[MAX_VREG_NUM];
            //The usage of the physical registers.
            // here 8 is the number of the register number of intel cup
            RegUsage  ra_reg_table[8];
            // identify if a virtual register is in a physical register
            bool  ra_vreg_spilled[MAX_VREG_NUM];
            // a pointer to the simulated source processor's registers
            XTUint32* source_regs;
    };

}

#endif
